//chartVo对象队列，排队生成报表
var chartVoObjQueue = {};
//报表定时任务对象
var chartQueueInterval = null;

/**
 * 根据统计报表VO对象生成报表插件所需的数据对象集合
 * @param chartVo 统计报表VO对象
 * @returns {Array}
 */
function createSeries(chartVo) {
	var type = chartVo.type; //统计报表类型
	var reportGroupVoList = chartVo.reportGroupVoList; //统计对象组集合
	var isXaxisNumber = chartVo.isXaxisNumber; //X轴是否为数值
	var series = []; //报表插件所需数据集
	if(reportGroupVoList && reportGroupVoList.length > 0) {
		$.each(reportGroupVoList, function(i, reportGroupVo){
			var groupName = reportGroupVo.groupName; //组名称
			var color = reportGroupVo.color; //组颜色
			var groupType = reportGroupVo.groupType; //组对应的报表类型
			var visible = reportGroupVo.visible; //组的隐藏属性
			var reportVoList = reportGroupVo.reportVoList; //统计节点集合
			var dataList = []; //统计节点数据集合
			if(reportVoList && reportVoList.length > 0) {
				$.each(reportVoList, function(j, reportVo){
					var name = reportVo.name; //统计节点名称
					var count = null; //统计节点数值
					if(chartVo.isDataInteger) {
						count = reportVo.integerCount; //显示整型数据
					} else {
						if(chartVo.isRealVal) {
							count = reportVo.realDoubleCount; //显示浮点型数据
						} else {
							count = reportVo.doubleCount; //显示浮点型数据(两位小数四舍五入)
						}
					}
					if(isXaxisNumber) {
						//如果X轴为数值，将X轴的字符串转换为数字
						dataList.push({x: parseFloat(name), y: count});
					} else {
						//如果X轴为字符串，进行默认的设置
						dataList.push([name, count]);
					}
				});
			}
			//数据对象
			var dataObj = {name: groupName, visible: visible, data: dataList};
			//如果设置了组颜色，进行颜色设置(由于饼图没分组，不需要进行组颜色设置)
			if(type !== "pie" && color) {
				dataObj.color = color;
			}
			//如果设置了组的报表类型，进行报表类型的设置
			if(groupType) {
				dataObj.type = groupType;
			}
			series.push(dataObj);
		});
	}
	return series;
}

/**
 * 通过统计报表VO对象生成统计报表(只在本js内部使用)
 * @param divId 统计报表的divId
 * @param chartVo 统计报表VO对象
 */
function createChartByVo(divId, chartVo) {
	if(divId && chartVo) {
		var reportGroupVoList = chartVo.reportGroupVoList; //统计对象组集合
		var yaxisUnitDesc = chartVo.yaxisUnitDesc; //Y轴描述
		var headerMsg = ""; //数据点提示的头部信息
		//如果不是整合为同一组的情况，并且统计组对象集合数大于1，证明出现多个统计组，数据点提示信息需要加上组名称前缀
		if(!chartVo.isMergeOneGroup && reportGroupVoList && reportGroupVoList.length > 1) {
			headerMsg = "{series.name}，"; //series.name为组名称
		}
		var chartOptions = null; //报表的options属性
		var barAndColPlotOptions = null; //柱状图的plotOptions属性
		var linePlotOptions = null; //折线图的plotOptions属性
		var piePlotOptions = null; //饼图的plotOptions属性
		var xAxisOptions = null; //X轴属性
		var yAxisOptions = null; //Y轴属性
		var type = chartVo.type; //统计报表类型
		chartOptions = {
			type: type //统计报表类型
		};
		//如果有显式指定报表宽度，使用指定的宽度
		if(chartVo.width) {
			chartOptions.width = chartVo.width;
		}
		//如果有显式指定报表高度，使用指定的高度
		if(chartVo.height) {
			chartOptions.height = chartVo.height;
		}
		//柱状图的plotOptions属性
		barAndColPlotOptions = {
	    	pointPadding: 0.2,
	        //pointWidth: 30,
	        borderWidth: 0,
	    	dataLabels: {
	            enabled: true,
	            color: '#000',
	            format: '{point.y}' + yaxisUnitDesc
	    	}
        };
		//如果统计类型为柱状图，并且只有一组统计数据的情况，如果统计节点数量不大于5，将柱宽调整为30
		if((type === "column" || type === "bar") && reportGroupVoList.length == 1) {
			var reportVoList = reportGroupVoList[0].reportVoList;
			if(reportVoList.length <= 5) {
				barAndColPlotOptions.pointWidth = 30;
			}
		}
		//如果将多组整合为一组的情况，将柱宽调整为30
		if(chartVo.isMergeOneGroup) {
			barAndColPlotOptions.pointWidth = 30;
			barAndColPlotOptions.groupPadding = 0.5; //设置每组的内边距
		}
		//折线图的plotOptions属性
		linePlotOptions = {
        	dataLabels: {
        		enabled: chartVo.isLineDataLabelsShow, //是否显示折线点的数据
        		color: '#000',
        		format: '{point.y}' + yaxisUnitDesc
        	},
        	lineWidth: 1,
        	marker: {
        		enabled: chartVo.isMarker, //是否显示折线图的点
        		radius: 3 //设置点的半径
        	},
        	enableMouseTracking: true //鼠标移动到统计点时的提示开关
        };
		//如果折线图屏蔽了折线点，提示信息只显示线的信息，不显示点的信息
		if(!chartVo.isMarker) {
			linePlotOptions.tooltip = {
				headerFormat: "{series.name}：",
				pointFormat: '{point.y}' + yaxisUnitDesc //Y轴数值
			};
			linePlotOptions.marker.radius = 0; //设置点的半径为零
			linePlotOptions.marker.lineColor = '{series.color}'; //设置点边框的颜色为当前线的颜色
			linePlotOptions.marker.lineWidth = 0; //设置点边框的半径为零
		}
		//如果需要屏蔽线条，进行线的隐藏
		if(chartVo.isHideLine) {
			linePlotOptions.lineWidth = 0;
		}
		//饼图的plotOptions属性
		piePlotOptions = {
			allowPointSelect: true,
        	cursor: 'pointer',
        	dataLabels: {
                enabled: true,
                color: '#000',
                connectorColor: '#000',
                format: '<b>{point.name}</b>：{point.y}' + yaxisUnitDesc
            },
			showInLegend: chartVo.isLegend //是否显示饼图图例
		};
		//有指定统计节点所显示的数值的字体大小的情况，进行字体大小的设置
		if(chartVo.plotOptionsFontSize) {
			//统计节点所显示数值的样式
			var plotOptionsStyle = {
				fontSize: chartVo.plotOptionsFontSize //统计节点所显示的数值的字体大小
			};
			if(type === "column" || type === "bar") {
				//设置柱状图的统计节点所显示的数值的字体大小
				barAndColPlotOptions.dataLabels.style = plotOptionsStyle;
			} else if(type === "line") {
				//设置折线图的统计节点所显示的数值的字体大小
				linePlotOptions.dataLabels.style = plotOptionsStyle;
			} else if(type === "pie") {
				//设置饼图的统计节点所显示的数值的字体大小
				piePlotOptions.dataLabels.style = plotOptionsStyle;
			}
		}
		//非饼图，即柱状图、折线图，需要设置X、Y轴属性
		if(type !== "pie") {
			//X轴属性设置
			xAxisOptions = {
	            title: {
	                text: chartVo.xaxisTitle, //X轴标题
	                style: {
						color: '#000',
						fontWeight: 'bold'
					}
	            },
	            labels: {
	            	style: {
	            		color: '#000',
	            		fontSize: '13px'
	            	},
	            	rotation: -45 //X轴名称逆时针旋转45度
	            }
			};
			//如果X轴显示的是字符串，设置X轴名称集合
			if(!chartVo.isXaxisNumber) {
				var xaxisNameList = chartVo.xaxisNameList;
				if(xaxisNameList && xaxisNameList.length > 0) {
					xAxisOptions.categories = xaxisNameList;
				}
			}
			//如果有设置X轴的刻度，进行设置
			var xaxisTickInterval = chartVo.xaxisTickInterval;
			if(xaxisTickInterval) {
				xAxisOptions.tickInterval = xaxisTickInterval;
			}
			//如果不需要显示X轴，或者整合为一组的情况，屏蔽X轴显示
			if(!chartVo.isXaxisShow || chartVo.isMergeOneGroup) {
				xAxisOptions.labels.enabled = false; //屏蔽X轴刻度值
				xAxisOptions.lineWidth = 0; //X轴线宽度为0
				xAxisOptions.tickWidth = 0; //X轴刻度宽度为0
			}
			//设置X轴显示的最大值(用于左右滚动报表)
			var xaxisMaxVal = chartVo.xaxisMaxVal;
			if(xaxisMaxVal) {
				xAxisOptions.max = xaxisMaxVal;
			}
			//Y轴属性设置
			yAxisOptions = {
	            title: {
	                text: chartVo.yaxisTitle, //Y轴标题
	                style: {
						color: '#000',
						fontWeight: 'bold'
					}
	            },
	            labels: {
	            	style: {
	            		color: '#000'
	            	},
	            	formatter: function() {
	            		return this.value + yaxisUnitDesc;
	            	}
	            },
	            min: chartVo.yaxisMinVal //Y轴的最小刻度(默认值为0，如果设置为null即恢复自动设置)
	        };
			//如果显示的是整型数据，禁用Y轴的小数显示
			if(chartVo.isDataInteger) {
				yAxisOptions.allowDecimals = false;
			}
			//如果不需要显示Y轴，屏蔽Y轴显示
			if(!chartVo.isYaxisShow) {
				yAxisOptions.labels.enabled = false; //屏蔽Y轴刻度值
			}
			//设置Y轴最大值
			if(chartVo.yaxisMaxVal) {
				yAxisOptions.max = chartVo.yaxisMaxVal;
			}
			//设置Y轴刻度
			if(chartVo.yaxisTickInterval) {
				yAxisOptions.tickInterval = chartVo.yaxisTickInterval;
			}
		}
		//图例配置
		var legendOptions = {
	        	enabled: chartVo.isLegend, //是否显示图例
	        	itemMarginTop: 2, //图例顶部margin
	        	itemMarginBottom: 2 //图例底部margin
	    };
		//标题配置
		var titleOptions = {
    		text: chartVo.title, //报表标题
            style: {
				fontSize: '20px',
				fontWeight: 'bold',
				color: '#000'
			}	
		};
		//设置标题大小
		if(chartVo.titleFontSize) {
			titleOptions.style.fontSize = chartVo.titleFontSize;
		}
		//图例需要显示在右上方的设置
		if(chartVo.isNeLegend) {
			legendOptions.align = "right"; //水平对齐居右
			legendOptions.verticalAlign = "top"; //垂直对齐居上
			legendOptions.floating = true; //图例浮动
			//legendOptions.y = 50; //图例Y坐标值(绝对定位的top)
		}
		//生成统计报表
		$(divId).highcharts({
			scrollbar: {
				enabled: chartVo.isScroll //设置报表是否需要左右滚动
			},
			//报表对象
			chart: chartOptions,
	        //统计对象颜色
	        colors: ["#003377", "#AA4643", "#89A54E", "#80699B", "#3D96AE", "#DB843D", "#666666", "#FFA07A", "#B5CA92",
	 	            "#FFBB00", "#33FF33", "#0000FF", "#FF0000", "#FF00FF", "#B8860B", "#92A8CD", "#8B4513", "#000000", "006400"],
	        //图例
	        legend: legendOptions,
	        //标题
	        title: titleOptions,
	        //副标题
	        subtitle: {
	            text: chartVo.subTitle, //报表副标题
	            style: {
					color: '#000'
				}
	        },
	        //X轴
	        xAxis: xAxisOptions,
	        //Y轴
	        yAxis: yAxisOptions,
	        //统计节点提示
	        tooltip: {
				headerFormat: headerMsg + '{point.key}：', //统计组名称(可无)，X轴名称
				pointFormat: '{point.y}' + yaxisUnitDesc //X轴数值(可无)，Y轴数值
			},
			//统计节点对象
	        plotOptions: {
	        	//柱状图(横向)节点数据显示设置
	            bar: barAndColPlotOptions,
	            //柱状图(纵向)节点数据显示设置
	            column: barAndColPlotOptions,
	            //折线图节点数据显示设置
	            line: linePlotOptions,
	            //饼图节点数据显示设置
	            pie: piePlotOptions
	        },
	        //报表数据集合
	        series: createSeries(chartVo), //根据统计报表VO对象生成报表插件所需的数据对象集合
	        //插件版权资料
	        credits: {
	            enabled: false //插件显示网址隐藏
	        }
	    });
	}
}

/**
 * 通过ChartVo对象生成统计报表
 * @param divId 统计报表的divId
 * @param chartVo 报表VO对象
 * @param options 报表生成参数
 */
function createChartByChartVo(divId, chartVo, options) {
	if(divId) {
		//如果找不到绑定图片的div，方法直接返回
		if($(divId).length == 0) {
			return;
		}
		//isQueue：是否使用队列，queueKey：队列标识，isCache：是否使用缓存，subDivKey：子div的key值(用于定义子div的id时使用)
		//sliderOptions：拖拉条属性配置(vAlign：垂直对齐方式(vertical，纵向，horizontal，横向),
		//val：默认值，min：最小值，max：最大值，step：步长，left：left样式(单位px)，top：top样式(单位px))
		var optionsCopy = {isQueue: false, queueKey: 'chartQueue', isCache: false, subDivKey: 'Chart', sliderOptions: false};
		if(options != null) {
			$.extend(optionsCopy, options); //覆盖options参数
		}
		if(chartVo) {
			//加载报表时，增加loading提示，报表div加边框
			$(divId).css({background: "url(" + $path + "/images/common/loading.gif" +") no-repeat center", border: "1px solid #CCC"});
			//当X轴为数值类型，同时需要显示拖拉条的情况
			if(chartVo.isXaxisNumber && optionsCopy.sliderOptions) {
				var sliderDivLeft = "0px"; //拖拉条div默认的left为0px
				//如果有指定拖拉条的left，进行设置
				if(optionsCopy.sliderOptions.left) {
					sliderDivLeft = optionsCopy.sliderOptions.left;
				}
				var sliderDivTop = "20px"; //拖拉条div默认的top为0px
				//如果有指定拖拉条的top，进行设置
				if(optionsCopy.sliderOptions.top) {
					sliderDivTop = optionsCopy.sliderOptions.top;
				}
				var vAlign = "vertical"; //拖拉条默认的垂直对齐方式为纵向
				//如果有指定拖拉条的垂直对齐方式，进行设置
				if(optionsCopy.sliderOptions.vAlign) {
					vAlign = optionsCopy.sliderOptions.vAlign;
				}
				var sliderDivLength = ""; //拖拉条长度
				if(vAlign === "vertical") {
					//如果拖拉条的垂直对齐方式为纵向，设置拖拉条div的高度为200px
					sliderDivLength = "height: 200px";
				} else if(vAlign === "horizontal") {
					//如果拖拉条的垂直对齐方式为横向，设置拖拉条div的宽度为200px
					sliderDivLength = "width: 200px";
				}
				//如果报表还没绑定拖拉条时，才需要绑定
				if($("#slider", divId).length === 0) {
					var sliderDiv = $("<div id='slider' style='float: left;cursor: pointer;position: relative;" + sliderDivLength 
							+ ";z-index: 10;top: " + sliderDivTop + ";left: " + sliderDivLeft + ";'>"
							+ "<label style='font-size:14px;position:relative;top:-25px;'>+</label>"
							+ "<label style='font-size:14px;position:relative;top:196px;left:-10px;'>_</label></div>")
					.slider({
						orientation: vAlign, //拖动条垂直对齐方式
						//range: "min",
						value: optionsCopy.sliderOptions.val, //当前值
						min: optionsCopy.sliderOptions.min, //最小值
						max: optionsCopy.sliderOptions.max, //最大值
						step: optionsCopy.sliderOptions.step, //步长
						slide: function(e, ui) {
							//如果拖拉条状态不可用，禁用拖拉
							if(!$("#slider", divId).data("enabled")) {
								return false;
							}
							var currSlideVal = ui.value; //当前拖拉条的值
							//如果因拖拉导致超出最大值，使用配置的最大值
							if(currSlideVal > optionsCopy.sliderOptions.max) {
								currSlideVal = optionsCopy.sliderOptions.max;
							}
							optionsCopy.sliderOptions.val = currSlideVal; //设置拖拉条属性配置中的值为当前值
							chartVo.xaxisMaxCount = -currSlideVal; //根据拖拉条当前值，设置x轴的最大个数(由于配置中进行了取反处理，因为要取反获取X轴最大个数)
							var slideUtils = {
								//根据X轴显示最大个数，设置X轴刻度的最大值
								opXaxisVal: function(chartVo) {
									var xaxisMaxCount = chartVo.xaxisMaxCount; //X轴显示的最大个数
									var xaxisNameList = chartVo.xaxisNameList; //X轴名称列表
									if(xaxisMaxCount && xaxisNameList.length > 0) {
										var xaxisValList = []; //X轴值集合
										//由于X轴为数值，将X轴名称转换为数字后，放入X轴值集合中
										$.each(xaxisNameList, function(i, xaxisName){
											xaxisValList.push(parseFloat(xaxisName));
										});
										xaxisValList.sort(function(a, b){return a > b ? 1 : -1;}); //将X轴的值进行升序
										var xaxisValListSize = xaxisValList.length;
										var xaxisValIndex = 0;
										if(xaxisMaxCount > xaxisValListSize) {
											//如果设置的X轴显示的最大个数大于X轴数值集合个数，X轴显示的最大值设置为X轴数值集合的最后一个值
											xaxisValIndex = xaxisValListSize - 1;
										} else {
											//如果设置的X轴显示的最大个数不大于X轴数值集合个数，根据X轴显示的最大个数来获取X轴的数值并设置为X轴显示的最大值
											xaxisValIndex = xaxisMaxCount - 1;
										}
										chartVo.xaxisMaxVal = xaxisValList[xaxisValIndex];
									}
									return chartVo;
								}
							};
							//重新设置X轴刻度的最大值
							chartVo = slideUtils.opXaxisVal(chartVo);
							//根据设置后的X轴属性重新生成报表
							createChartByChartVo(divId, chartVo, optionsCopy);
						}
					}).data("enabled", true); //缓存"enabled"标识拖拉条可使用
					//当鼠标移进"+-"符号时，禁用拖拉条，鼠标移出"+-"符号时，启用拖拉条
					$("#slider label", divId).live("mouseenter", function(){
						$("#slider", divId).data("enabled", false);
					}).live("mouseleave", function(){
						$("#slider", divId).data("enabled", true);
					});
					//报表div添加拖拉条
					$(divId).append(sliderDiv);
				}
			}
			if($.browser.msie && optionsCopy.isQueue) {
				//如果是IE浏览器并且设置了使用队列，使用队列生成报表的情况
				chartVoObjQueue[divId] = {divId: divId, chartVo: chartVo, options: optionsCopy};
				//添加了报表队列元素，如果报表定时任务为空，触发定时任务
				if(chartQueueInterval == null) {
					chartQueueInterval = setInterval("createChartBySpace()", 1000);
				}
			} else {
				//不使用队列生成报表的情况，通过统计报表VO对象生成统计报表
				opChartByCondition(divId, chartVo, optionsCopy);
			}
		}
	}
}

/**
 * 通过Url的Ajax请求生成统计报表
 * @param divId 统计报表的divId
 * @param url 请求地址
 * @param param url请求参数
 * @param options 报表参数对象
 * (isQueue：是否使用队列，isCache：是否使用缓存，subDivKey：子div的key)
 * @param subDivKey 子div的key
 */
function createChartByUrl(divId, url, param, options) {
	if(divId && url) {
		$.post(url, param, function($data){
			createChartByChartVo(divId, $data.chartVo, options);
		}, 'json');
	}
}

/**
 * 从ChartVo队列中获取报表VO对象，生成报表(每1秒做一次)
 */
function createChartBySpace() {
	if(chartVoObjQueue && !$.isEmptyObject(chartVoObjQueue)) {
		//var deleteIndexArrs = [];
		var deleteDivIds = []; //需要移除报表队列任务的divId
		$.each(chartVoObjQueue, function(divId, chartVoObj){
			//var chartVoObj = chartVoObjQueue[0];
			//var divId = chartVoObj.divId; //报表父divId
			var chartVo = chartVoObj.chartVo; //报表VO对象
			var options = chartVoObj.options; //报表参数对象
			//根据条件控制报表生成
			var containerHeight = $(divId).parents(".chartContainer").height(); //容器高度
			var chartDivHalfHeight = $(divId).height() / 2; //报表div的一半高度
			var chartDivPosition = $(divId).position(); //报表div位置
			//能正常获取报表div位置的情况，根据滚动距离的判断，生成报表
			if(chartDivPosition) {
				var chartDivPositionTop = chartDivPosition.top; //报表div位置的Top值
				/*当报表div位置大于零时，报表生成区间在零到报表div一半高度的位置
				/当报表div位置小于零时，报表生成区间在负数的报表div一半高度到零*/
				if((chartDivPositionTop > 0 && chartDivPositionTop < containerHeight - chartDivHalfHeight) 
						|| (chartDivPositionTop < 0 && chartDivPositionTop > -chartDivHalfHeight)) {
					opChartByCondition(divId, chartVo, options);
					//报表已生成，保存需要从队列中移除的报表VO对象的下标
					//deleteIndexArrs.push(i);
					deleteDivIds.push(divId);
				}
			}
		});
		/*$.each(deleteIndexArrs, function(i, deleteIndex){
			//报表生成完毕(如果报表已存在只显示div不调用报表生成方法)，移除队列中当前操作的ChartVo对象
			chartVoObjQueue.splice(deleteIndex, 1);
		});*/
		$.each(deleteDivIds, function(i, divId){
			delete chartVoObjQueue[divId];
		});
	} else {
		//如果报表任务队列为空，清空报表定时任务
		clearInterval(chartQueueInterval);
		chartQueueInterval = null;
	}
}

/**
 * 根据条件控制报表生成
 * @param divId div父亲id
 * @param chartVo 报表VO对象
 * @param options 报表生成参数
 */
function opChartByCondition(divId, chartVo, options) {
	var subDivKey = options.subDivKey; //生成报表子div的key
	var subDivId = divId.substring(divId.lastIndexOf("#") + 1) + subDivKey; //报表子divId
	var subDiv = $("#" + subDivId, $(divId)); //根据id获取子div
	var g = {
		//创建一个新的子div，并生成报表
		createNewChart: function(divId, subDivId, chartVo) {
			var subDivStyle = ""; //报表子div样式设置
			//当X轴为数值类型，同时需要显示拖拉条的情况，设置报表子div的宽度和向右浮动(避免在IE浏览器下出现换行问题)
			if(chartVo.isXaxisNumber && options.sliderOptions) {
				//报表子div的宽度  = 报表div宽度  - 拖拉条div宽度  - 10 (由于出现边框问题，所以还需要减10px)
				var subDivWidth = $(divId).width() - $("#slider", divId).width() - 5;
				subDivStyle = " style='width: "+subDivWidth+"px;float:right;'";
			}
			//根据id生成一个子div，并绑定报表
			$(divId).append($("<div id='" + subDivId + "'" + subDivStyle + "></div>"));
			//setTimeout(function(){
				createChartByVo(divId + " #" + subDivId, chartVo);
				//生成报表后，清除报表div边框
				$(divId).css({background: "none", border: "none"});
			//}, 500);
		}
	};
	if(subDiv && subDiv.length > 0) {
		if(options.isCache) {
			//如果需要使用缓存的情况，而且当前子div存在，隐藏同辈的所有子div，并显示当前的子div
			$(divId).children().each(function(){
				$(this).hide();
			});
			subDiv.show();
		} else {
			//如果不需要使用缓存的情况，先删除当前子div，生成一个新的子div，并绑定报表
			subDiv.remove();
			g.createNewChart(divId, subDivId, chartVo);
		}
	} else {
		//如果当前子div不存在，生成一个新的子div，并绑定报表
		g.createNewChart(divId, subDivId, chartVo);
	}
}